﻿#include "QtKLog.h"

#include "QtChCharset.h"

#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
#include <QtCore/QMutex>
#include <QtCore/QDir>
#include <QtCore/QDateTime>
#include <QtWidgets/QMessageBox>

#ifdef Q_OS_WIN
#   include <windows.h>
#endif
QtKLog::QtKLog(QObject *parent) : QObject(parent)
{
}

QtKLog::~QtKLog()
{
    CloseLogFile();
}

QtKLog& QtKLog::Instance()
{
    static QtKLog instance;
    return instance;
}

void QtKLog::InstallMessageHandler()
{
    if(!mhOldMessageHandler)
    {
        mhOldMessageHandler = qInstallMessageHandler(QtKLog::KMessageLogOutput);
    }
}

void QtKLog::UninstallMessageHandler()
{
    if(mhOldMessageHandler)
    {
        qInstallMessageHandler(mhOldMessageHandler);
        mhOldMessageHandler = nullptr;
    }
}

void QtKLog::CloseLogFile()
{
    if (mbOpen)
    {
        mFile.flush();
        mFile.close();
        mbOpen = false;
    }
}

void QtKLog::WriteLogFile(QString strMessage)
{
    if (!mbOpen)
    {// 没有打开文件
        return;
    }
    // 加锁
    static QMutex mutex;
    mutex.lock();
    //if (CreateLogFile())
    {
        mStream << strMessage << "\r\n";
        mStream.flush();
        mFile.flush();
    }
    // 解锁
    mutex.unlock();
}

bool QtKLog::CreateLogFile()
{
    if (mbOpen)
    {
        return mbOpen;
    }
    QString dirPath = QCoreApplication::applicationDirPath();
    dirPath += "\\log";
    QDir dirTmp;
    dirTmp.mkpath(dirPath);
    //dirPath = "d:";
    QString strFileName = QObject::tr("%1\\log_%2.log").arg(dirPath).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-HHmmss"));
    mFile.setFileName(strFileName);
    if (!mFile.open(QIODevice::ReadWrite | QIODevice::Append))
    {
        static bool bFlag = true;
        if (bFlag)
        {
            bFlag = false;
            QMessageBox::warning(nullptr, "warning", "create log failed");
            QMessageBox::warning(nullptr, "warning", dirPath);
        }
        return false;
    }
    //QMessageBox::information(NULL, "information", dirPath);

    mStream.setDevice(&mFile);
    mbOpen = true;
    SetWriteLogFile(true);
    return true;
}

bool QtKLog::WriteLogFile()
{
    return mbWriteLogFile;
}

void QtKLog::SetWriteLogFile(bool bVal)
{
    mbWriteLogFile = bVal;
}

bool QtKLog::SendLogSignal()
{
    return  mbSendLogSignal;
}

void QtKLog::SetSendLogSignal(bool bVal)
{
    mbSendLogSignal = bVal;
}

bool QtKLog::Single()
{
    return mbSingle;
}

void QtKLog::SetSingle(bool bVal)
{
    mbSingle = bVal;
}

//void QtKLog::KMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
//{
//	QByteArray localMsg = msg.toLocal8Bit();
//	char szBuffer[10240] = { 0 };
//	switch (type)
//	{
//	case QtDebugMsg:
//		sprintf_s(szBuffer, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
//		break;
//	case QtInfoMsg:
//		sprintf_s(szBuffer, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
//		break;
//	case QtWarningMsg:
//		sprintf_s(szBuffer, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
//		break;
//	case QtCriticalMsg:
//		sprintf_s(szBuffer, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
//		break;
//	case QtFatalMsg:
//		sprintf_s(szBuffer, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
//	}
//	OutputDebugStringA(szBuffer);
//}

void QtKLog::KMessageLogOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QString strMessage;
    if(!QtKLog::Instance().Single())
    {
        QString strMsgType("");
        switch (type)
        {
        case QtDebugMsg:
            strMsgType = QString("Debug");
            break;
        case QtWarningMsg:
            strMsgType = QString("Warning");
            break;
        case QtCriticalMsg:
            strMsgType = QString("Critical");
            break;
        case QtFatalMsg:
            strMsgType = QString("Fatal");
            break;
        case QtInfoMsg:
            strMsgType = QString("Info");
            break;
        default:
            strMsgType = QString("Unkown");
            break;
        }
        // 设置输出信息格式
        QString strDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz");
        strMessage = QString("%1 %2 %3 \t\t\t\t\t\t\t\t\t\tFunction:%4\t\t\t\tFile:%5:%6 ")
                .arg(strDateTime).arg(strMsgType).arg(msg).arg(context.function).arg(context.file).arg(context.line);

        //QByteArray localMsg = strMessage.toLocal8Bit();
    }
    else
    {
        strMessage = msg;
    }

    if(QtKLog::Instance().SendLogSignal())
    {// 发送信号
        QtKLog::Instance().signalLogMsg(strMessage);
    }
    if(QtKLog::Instance().WriteLogFile())
    {// 输出日志到文件中
        QtKLog::Instance().WriteLogFile(strMessage);
    }
#if (defined(_DEBUG) || defined(LOG_TO_OutputDebugString)) && defined(Q_OS_WIN)
    //QByteArray localMsg = strMessage.toLocal8Bit();
    //localMsg += "\n";
    //OutputDebugStringA(localMsg.data());
#endif
    if(QtKLog::Instance().mhOldMessageHandler)
    {// 使用默认日志输出进行到IDE的输出窗口
        QtKLog::Instance().mhOldMessageHandler(type, context, msg);
    }
}
